package ObjectInfo;

import gui.ObjectInfoDialog;
import houseHold.GHObject;
import houseHold.House;
import houseHold.HouseHoldObject;
import houseHold.ObjectType;
import houseHold.Room;
import houseHold.electricObjects.ElectricObjectType;
import houseHold.gasObjects.GasObjectType;
import houseHold.waterObjects.WaterObjectType;

import java.awt.Color;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ExecutionException;

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;

import sensor.Sensor;
import consumption.ConsumptionType;

public class ObjectTableModel extends AbstractTableModel {
	private static final String[] columnNames = { "Name", "Type", "Location",
			"Sensor", "Consumption", "Consumption Type", "Edit" };
	private static Vector<String> nameList = new Vector<String>();
	private static final long serialVersionUID = 5694519438649295192L;
	private Room callingRoom;

	private int consumption;

	private ConsumptionType cType;

	private Vector<Object[]> data;

	private HashMap<Integer, Integer> list;

	private Room location;

	private String objectName;

	private ObjectType objectType;

	private boolean once = false;

	private Sensor sensor;

	JTable table;
	private JComboBox typeComboBox, locationComboBox, sensorComboBox,
			consumptionType;

	public ObjectTableModel(Room cRoom) {
		super();
		list = new HashMap<Integer, Integer>();
		callingRoom = cRoom;
		init();
		System.out.println(columnNames[2]);
	}

	@Override
	public Class<? extends Object> getColumnClass(int c) {
		return getValueAt(0, c).getClass();
	}

	@Override
	public int getColumnCount() {
		return 7;
	}

	@Override
	public String getColumnName(int col) {
		return columnNames[col];
	}

	public Vector<Object[]> getData() {
		return data;
	}

	private void getData(HouseHoldObject o) {
		objectName = o.getName();
		objectType = o.getType();
		location = o.getLocation();
		sensor = o.getSensor();
		consumption = o.getConsumption();
		cType = o.getConsumptionType();
	}

	@Override
	public int getRowCount() {
		return data.size();
	}

	public Object getValueAt(int row, int col) {
		return data.get(row)[col];
	}

	public void init() {
		nameList = new Vector<String>();
		data = new Vector<Object[]>();
		if (callingRoom.getItemList().size() > 0) {
			Set<String> keySet = callingRoom.getItemList().keySet();
			Iterator<String> it = keySet.iterator();
			int i = 0;
			while (it.hasNext()) {
				getData(callingRoom.getItemList().get(it.next()));
				if (!once)
					list.put(callingRoom.getItem(objectName).getID(), i);
				data.add(new Object[7]);
				data.get(i)[0] = objectName;
				data.get(i)[1] = objectType;
				data.get(i)[2] = location.getName();
				data.get(i)[3] = sensor;
				data.get(i)[4] = consumption + "";
				data.get(i)[5] = cType;
				if (data.get(i)[6] == null)
					data.get(i)[6] = Boolean.FALSE;
				i++;
				nameList.add(objectName);
			}
			once = true;
		}

	}

	@Override
	public boolean isCellEditable(int row, int col) {
		if (data.get(row)[6] == Boolean.TRUE || col == 6)
			return true;
		return false;
	}

	public void setTable(JTable objectList) {
		this.table = objectList;

	}

	private void setUpConsumptionColumn(JTable table, TableColumn column) {
		consumptionType = new JComboBox();
		consumptionType.setBackground(new Color(255, 255, 245));
		if (callingRoom.hasGasSensor())
			consumptionType.addItem("gas");
		if (callingRoom.hasWaterSensor())
			consumptionType.addItem("water");
		if (callingRoom.hasElectricSensor())
			consumptionType.addItem("electricity");
		column.setCellEditor(new DefaultCellEditor(consumptionType));
		DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
		renderer.setToolTipText("Click for combo box");
		column.setCellRenderer(renderer);

	}

	private void setUpLocationColumn(JTable table, TableColumn column) {
		locationComboBox = new JComboBox(House.getInstance().getRoomNames());
		locationComboBox.setBackground(new Color(255, 255, 245));
		column.setCellEditor(new DefaultCellEditor(locationComboBox));
		DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
		renderer.setToolTipText("Click for combo box");
		column.setCellRenderer(renderer);
	}

	private void setUpObjectTypeRow(JTable table, TableColumn column) {
		EachRowEditor rowEditor = new EachRowEditor(table);
		Set<String> keySet = callingRoom.getItemList().keySet();
		Iterator<String> it = keySet.iterator();
		int i = 0;
		while (it.hasNext()) {
			ConsumptionType type = callingRoom.getItemList().get(it.next())
					.getConsumptionType();
			typeComboBox = new JComboBox();
			typeComboBox.setBackground(new Color(255, 255, 245));
			switch (type) {
			case GAS:
				typeComboBox = new JComboBox(GasObjectType.GAS_OBJECT.getList());
				break;
			case WATER:
				typeComboBox = new JComboBox(WaterObjectType.WATER_OBJECT
						.getList());
				break;
			case ELECTRICITY:
				typeComboBox = new JComboBox(ElectricObjectType.ELECTRIC_OBJECT
						.getList());
				break;
			default:
				break;
			}
			rowEditor.setEditorAt(i, new DefaultCellEditor(typeComboBox));
			i++;
			table.getColumn("Type").setCellEditor(rowEditor);
			DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
			renderer.setToolTipText("Click for combo box");
			column.setCellRenderer(renderer);
		}

	}

	private void setUpSensorColumn(JTable table, TableColumn column) {
		EachRowEditor rowEditor = new EachRowEditor(table);
		for (int i = 0; i < nameList.size(); i++) {
			ConsumptionType cType = callingRoom.getItem(nameList.get(i))
					.getConsumptionType();
			sensorComboBox = new JComboBox(callingRoom.getSensorList(cType));
			sensorComboBox.setBackground(new Color(255, 255, 245));
			rowEditor.setEditorAt(i, new DefaultCellEditor(sensorComboBox));
			table.getColumn("Sensor").setCellEditor(rowEditor);
			DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
			renderer.setToolTipText("Click for combo box");
			column.setCellRenderer(renderer);
		}/*
		 * sensorComboBox = new JComboBox(); Set<String>
		 * keySet=callingRoom.getSensors().keySet(); Iterator<String>
		 * it=keySet.iterator(); while(it.hasNext()){ String key=it.next();
		 * sensorComboBox.add callingRoom.getSensorList(consumptionType);
		 * sensorComboBox.addItem(callingRoom.getSensors().get(it.next())); }
		 * column.setCellEditor(new DefaultCellEditor(sensorComboBox));
		 * DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
		 * renderer.setToolTipText("Click for combo box");
		 * column.setCellRenderer(renderer);
		 */
	}

	@Override
	public void setValueAt(Object value, int row, int col) {
		data.get(row)[col] = value;
		fireTableCellUpdated(row, col);
		updateRoom(value, row, col);
		updateTable(ObjectInfoDialog.ObjectList);
		ObjectInfoDialog.ObjectList.repaint();

	}

	private void update() {

		nameList = new Vector<String>(callingRoom.getItemCount());
		nameList.setSize(callingRoom.getItemCount());
		Set<String> keySet = callingRoom.getItemList().keySet();
		Iterator<String> it = keySet.iterator();
		int i = 0;
		while (it.hasNext()) {
			getData(callingRoom.getItemList().get(it.next()));
			int line = list.get(callingRoom.getItem(objectName).getID());
			data.get(line)[0] = objectName;
			data.get(line)[1] = objectType;
			data.get(line)[2] = location.getName();
			data.get(line)[3] = sensor;
			data.get(line)[4] = consumption + "";
			data.get(line)[5] = cType;
			nameList.set(line, objectName);

			System.out.println(Arrays.asList(data.get(i)));
			i++;
		}

	}

	public void updateRoom(final Object value, final int row, int col) {
		final String cON = nameList.get(row);
		System.out.println(callingRoom);
		System.out.println(callingRoom.getItem(cON));
		switch (col) {
		case 0:
			callingRoom.getItem(cON).setName((String) value);
			break;
		case 1: {
			ObjectType oType;
			switch (callingRoom.getItem(cON).getConsumptionType()) {
			case GAS:
				oType = GasObjectType.GAS_OBJECT;
				break;
			case WATER:
				oType = WaterObjectType.WATER_OBJECT;
				break;
			case ELECTRICITY:
				oType = ElectricObjectType.ELECTRIC_OBJECT;
				break;
			default:
				oType = GHObject.OBJECT;
				break;
			}
			oType = oType.match((String) value);
			if (oType == null)
				oType = GHObject.OBJECT;
			callingRoom.getItem(cON).setType(oType, true);
			break;
		}
		case 2: {
			if (callingRoom.getName() == (String) value)
				break;
			else {
				ObjectInfoDialog.ShowWarning();
				SwingWorker<Boolean, Boolean> worker = new SwingWorker<Boolean, Boolean>() {
					@Override
					public Boolean doInBackground() {
						while (!table.isEnabled()) {
							try {
								Thread.sleep(100);
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
						return ObjectInfoDialog.canMove;
					}

					@Override
					public void done() {
						try {
							boolean res = get();
							if (res) {
								callingRoom.getItem(cON).moveItem(
										House.getInstance().getRoom(
												(String) value));
								data.remove(row);
								fireTableRowsDeleted(row, row);
							}
						} catch (InterruptedException ex) {
							ex.printStackTrace();
						} catch (ExecutionException ex) {
							ex.printStackTrace();
						}
					}
				};
				worker.execute();
			}
			break;
		}
		case 3: {
			callingRoom.getItem(cON).setSensor((Sensor) value);
			// callingRoom.setItem(cON,callingRoom.getItem(cON).modifyConsumptionType(ConsumptionType.match(callingRoom.getItem(cON).getSensor().getSensorRecord().toString())));
			// callingRoom.getItem(cON).setType(ConsumptionType.getGenericType(callingRoom.getItem(cON).getConsumptionType()),true);
			break;
		}
		case 4:
			callingRoom.getItem(cON).setConsumption(
					Integer.parseInt((String) value));
			break;

		case 5: {
			System.out.println("CON=" + cON);
			callingRoom.setItem(cON, callingRoom.getItem(cON)
					.modifyConsumptionType(
							ConsumptionType.match((String) value)));
			System.out.println("CON=" + cON);
			System.out.println("STUFF=" + callingRoom.getItem(cON));
			System.out.println("stuffended");
			int id = callingRoom.getItem(cON).getID();
			String cONAUX = id
					+ "#"
					+ ConsumptionType.getGenericType(
							callingRoom.getItem(cON).getConsumptionType())
							.toString();
			callingRoom.getItem(cON).setType(
					ConsumptionType.getGenericType(callingRoom.getItem(cON)
							.getConsumptionType()), true);
			System.out.println("LALALALA"
					+ callingRoom.getItem(cONAUX).getConsumptionType());
			callingRoom.getItem(cONAUX).setSensor(
					callingRoom.getSensor(callingRoom.getItem(cONAUX)
							.getConsumptionType()));
			break;
		}
		default:
			break;
		}

	}

	public void updateTable(JTable table) {
		update();
		setUpObjectTypeRow(table, table.getColumn("Type"));
		setUpLocationColumn(table, table.getColumn("Location"));
		setUpSensorColumn(table, table.getColumn("Sensor"));
		setUpConsumptionColumn(table, table.getColumn("Consumption Type"));
	}

}
